package main;

import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.db.ds.DSFactory;
import cn.hutool.db.ds.druid.DruidDSFactory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import entity.PmDeatil;
import entity.Pubmed;
import lombok.SneakyThrows;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import utils.SmallTool;
import utils.StringUtil;

import javax.sql.DataSource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @Author: gcr
 * @Date: 2022-3-14 8:31
 */
public class compareboospm {

    @SneakyThrows
    public static void main(String[] args) {
        String dbNameMy = "pubmed_vip_extend_new_new";
        String dbNameBoss = "pmid_doi_down_1_500w";

        int effectSize = 0;

        int startPmid = 0;
        int endPmid = 100000;
        int breakSize = 10000;


        //存放比对结果
        Map<String, Integer> resMapConpare = new ConcurrentHashMap<>();

        // 用于存放doi 只有一方有的情况 打印出来
        Map<Integer, String> pmidDoi = new LinkedHashMap<>();
        // 双方doi不同
        Map<Integer, String> pmidDoiNoSame = new LinkedHashMap<>();


        SmallTool.printMemory();
        DSFactory.setCurrentDSFactory(new DruidDSFactory());
        DataSource ds = DSFactory.get("server_local");
        DataSource ds2 = DSFactory.get("server_local3307");
        Db use = Db.use(ds);
        Db use3307 = Db.use(ds2);

        // 需要对比的数据如下
        //doi	  `citationDoi` varchar(90) DEFAULT NULL,
        //mh-mhy	  `meshSet` text,
        //pm	  `pmid` int(8) DEFAULT NULL,
        //Review	  `typeSet` text,
        //Substances	  `subSet` text,
        //标题	  `citationTitle` text,
        //关键词	  `keyWords` text,
        //来源	  `citationJournalTitle` varchar(120) DEFAULT NULL,
        //年卷期-页码	  `text` text,
        //未确认	  `linkSet` text,
        //未确认	  `figure` longtext,
        //摘要	  `abs` longtext,
        //作者	  `authorMap` text,
        //作者地址	  `addressMap` longtext,

        String allDate = "select max(pmid) as pmid  from " + dbNameBoss;
        Entity query = use3307.query(allDate).get(0);
        SmallTool.printMess("最大的id 是" + query.getStr("pmid"));


//        int startPmid = 2000001;
//        int endPmid = 3000000;

        Integer count = query.getInt("pmid");
        int pageSize = count / breakSize + 1;
        SmallTool.printMess("全部页码+++++++++" + pageSize);
//        SmallTool.printMess("即将开始请提前关闭如果想的话十秒倒计时");
//        SmallTool.SleepMillis(10000L);
        SmallTool.printMess("任务开始+++++++++++++++++++++++++++++++++++++++++++++++++++++");

        for (int i = 1; i <= pageSize; i++) {
            int start = breakSize * (i - 1) + 1;
            int end = i * breakSize;
//            SmallTool.printMess("开始id++" + start + "+++结束id++++" + end);
            if (end <= startPmid) {
//                SmallTool.printMess("因为小于" + startPmid + " 略过了");
                continue;
            }

            if (end > endPmid) {
//                SmallTool.printMess("因为小于" + startPmid + " 略过了");
                continue;
            }
            SmallTool.printMess("当前页码+++++" + i);
            SmallTool.printMemory();

            String boss = "select * from " + dbNameBoss + " where pmid between " + start + " and " + end;
            String me = "select * from " + dbNameMy + " where pmid between " + start + " and " + end;
            List<Entity> queryBoss = use3307.query(boss);
            List<Pubmed> queryMe = use.query(me, Pubmed.class);

            // 相比对 doi pmid 标题
            for (Pubmed pmDeatil : queryMe) {
                effectSize++;
                Integer pmid = pmDeatil.getPmid();
//                    SmallTool.printMess("开始比对pmid++++++++++++++++++" + pmid);
                String title = handleStr(pmDeatil.getArticleTitle());
                if (title == null) {
                    handleCompareSize(resMapConpare, "我的标题是空++++");
                    //SmallTool.printMessError("我的标题是空++++");
                    continue;
                }
                String doi = pmDeatil.getDoi();
                Optional<Entity> pmid1Boss = queryBoss.stream().filter(o -> o.getInt("pmid").equals(pmid)).findFirst();
                if (pmid1Boss.isPresent()) {
                    Entity entityBoss = pmid1Boss.get();
                    String boosTitle = handleStr(entityBoss.getStr("citationTitle"));
                    String boosDoi = entityBoss.getStr("citationDoi");
                    // title
                    if (!title.equals(boosTitle)) {
                        handleCompareSize(resMapConpare, "不同标题++");
                        //SmallTool.printMessError("不同标题++" + pmid);
                        continue;
                    }
                    // doi
                    if (StringUtil.isNotNull(doi) && StringUtil.isNotNull(boosDoi)) {
                        if (!doi.equals(boosDoi)) {
                            handleCompareSize(resMapConpare, "都不不同doi++");
                            handleCompareSizePmidDoi(pmidDoiNoSame, pmid, doi);
                            //SmallTool.printMessError("不同doi++" + pmid);
                            continue;
                        }
                    } else if (StringUtil.isNull(doi) && StringUtil.isNotNull(boosDoi)) {
                        handleCompareSizePmidDoi(pmidDoi, pmid, boosDoi);
                        handleCompareSize(resMapConpare, "一方有不同doi++");
                        //SmallTool.printMessError("不同doi++" + pmid);
                        continue;
                    } else if (StringUtil.isNotNull(doi) && StringUtil.isNull(boosDoi)) {
                        handleCompareSizePmidDoi(pmidDoi, pmid, doi);
                        //SmallTool.printMessError("不同doi++" + pmid);
                        handleCompareSize(resMapConpare, "一方有不同doi++");
                        continue;
                    } else if (doi == null && boosDoi == null) {
                        //SmallTool.printMessError("doi都是null++" + pmid);
                        handleCompareSize(resMapConpare, "doi都是null++");

                        continue;
                    }
                    //Review
//                    pmDeatil.get
                    String pts = pmDeatil.getPts();
                    Set<String> ptsMySet = new HashSet<>();
                    // 无法处理暂时
                    if (StringUtil.isNotNull(pts)) {
                        List<PmDeatil.AssociatedData> ptsList = JSONArray.parseArray(pts, PmDeatil.AssociatedData.class);
                        ptsMySet = ptsList.stream().map(o -> o.getTitle()).collect(Collectors.toSet());
                        ptsMySet.removeAll(getErrorPts());
                    }
                    if (ptsMySet.size() > 0) {
                        String subSet = entityBoss.getStr("typeSet");
                        if (subSet.equals("[]")) {
                            //SmallTool.printMessError("pts错误++++" + pmid);
                            handleCompareSize(resMapConpare, "pts错误++++");

                            continue;
                        } else {
                            List<String> strings = JSONArray.parseArray(subSet, String.class);
                            if (strings.size() != ptsMySet.size()) {
                                //SmallTool.printMessError("错误pst不一致+++" + pmid);
                                handleCompareSize(resMapConpare, "错误pst不一致+++");

                                continue;
                            }
                            if (!strings.containsAll(ptsMySet)) {
                                handleCompareSize(resMapConpare, "错误pst不一致+++");
                                //SmallTool.printMessError("错误pst不一致+++" + pmid);
                                continue;
                            }
                        }
                    }
                    // mesh词
                    String meshHeadingy = pmDeatil.getMeshHeading() == null ? "" : pmDeatil.getMeshHeading();
                    String meshSetBoos = entityBoss.getStr("meshSet");
                    List<String> myMesHY = Arrays.asList(meshHeadingy.split(";"));
                    Set<String> myMesh = new HashSet<>();
                    TestMesh.getMeSHSet(myMesh, myMesHY);
                    if (myMesh.size() > 0 && meshSetBoos.equals("[]")) {
                        handleCompareSize(resMapConpare, "老本mesh词是空++");

                        //SmallTool.printMessError("mesh词错误++" + pmid);
                        continue;
                    } else if (myMesh.size() == 0 && !meshSetBoos.equals("[]")) {
                        handleCompareSize(resMapConpare, "我的mesh词是空++");

                        //SmallTool.printMessError("mesh词错误++" + pmid);
                        continue;
                    } else {
                        List<String> meshBoss = JSONArray.parseArray(meshSetBoos, String.class);
                        meshBoss = parseMesh(meshBoss);
                        if (meshBoss.size() != myMesh.size()) {
                            handleCompareSize(resMapConpare, "mesh词数量不一致+++");
                            //SmallTool.printMessError("mesh词错误++" + pmid);
                            continue;
                        }
                        if (!meshBoss.containsAll(myMesh)) {
                            handleCompareSize(resMapConpare, "mesh词错误+++");

                            //SmallTool.printMessError("mesh词错误+++" + pmid);
                            continue;
                        }
                    }
                    //Substances
                    Set<String> SubstancesmY = new HashSet<>();
                    String mySubs = pmDeatil.getSubs();
                    if (StringUtil.isNotNull(mySubs)) {

                        List<PmDeatil.AssociatedData> ptsList = JSONArray.parseArray(mySubs, PmDeatil.AssociatedData.class);
                        SubstancesmY = ptsList.stream().map(o -> o.getTitle()).collect(Collectors.toSet());
                    }
                    List<String> stringsBossSub = JSONArray.parseArray(entityBoss.getStr("subSet"), String.class);
                    if (SubstancesmY.size() != stringsBossSub.size()) {
                        handleCompareSize(resMapConpare, "Substances错误++");

                        //SmallTool.printMessError("Substances错误++" + pmid);
                        continue;
                    } else {
                        if (!SubstancesmY.containsAll(stringsBossSub)) {
                            handleCompareSize(resMapConpare, "Substances错误++");

                            //SmallTool.printMessError("Substances错误++" + pmid);
                            continue;
                        }
                    }
                    // 关键词
                    String keywordMe = pmDeatil.getKeyword();
                    String keywordBoss = entityBoss.getStr("keyWords");
                    if (keywordBoss.equals("")) {
                        keywordBoss = null;
                    }
                    if (keywordMe == null && keywordBoss != null) {
                        handleCompareSize(resMapConpare, "keyword错误++");
                        //SmallTool.printMessError("keyword错误++" + pmid);
                        continue;
                    }
                    if (keywordMe != null && keywordBoss == null) {
                        handleCompareSize(resMapConpare, "keyword错误++");
                        //SmallTool.printMessError("keyword错误++" + pmid);
                        continue;
                    }

//                    Document parseme = Jsoup.parse(keywordMe);
                    // 部分不一致 无法对比
                    //来源
                    String sourceBoss = entityBoss.getStr("citationJournalTitle").equals("") ? null : entityBoss.getStr("citationJournalTitle");
                    String meSsource = pmDeatil.getJour();
                    if (sourceBoss != null && meSsource == null) {
                        handleCompareSize(resMapConpare, "期刊错误+++");

                        //SmallTool.printMessError("期刊错误+++" + pmid);
                        continue;
                    }

                    if (!sourceBoss.equals(meSsource)) {
                        handleCompareSize(resMapConpare, "期刊错误+++");

                        //SmallTool.printMessError("期刊错误+++" + pmid);
                        continue;
                    }
                    //  卷 期 页
                    String volume = pmDeatil.getVolume();
                    String pubDate = pmDeatil.getPubDate();
                    String pubDateMedline = pmDeatil.getMedlineDate();
                    String issue = pmDeatil.getIssue();
                    String pasge = pmDeatil.getPages();
                    String ISSusBoss = entityBoss.getStr("text");
                    pubDate = pubDate.replace("-", " ").trim();
                    pubDate = handleIssue(pubDate).trim();
                    String paramIsuus = "";
                    if (StringUtil.isNotNull(issue)) {
                        paramIsuus = "(" + issue + "):";
                    }
                    String voIssBreak = "";
                    if (paramIsuus.startsWith("(")) {
                        voIssBreak = "";
                    } else {
                        voIssBreak = ":";
                    }
                    String MYISS = pubDate + ";" + volume + voIssBreak + paramIsuus + pasge + ".";
                    MYISS = MYISS.replace(";:", ";");
                    if (!MYISS.equals(ISSusBoss)) {
                        // 进行比对带有medline的日期
                        String myMedlineYear = pubDateMedline.split(" ")[0].trim();
                        String myMedlineRest = pubDateMedline.replace(myMedlineYear, "").trim();
                        String s = myMedlineRest + " " + myMedlineYear + ";" + volume + paramIsuus + pasge + ".";
                        //情况太多来的 值匹配年和和后面的数据 其他不看了
                        String[] splitBoss = ISSusBoss.split(";");
                        String splitBoss1 = splitBoss[0];
                        String bossRest = splitBoss[1];
                        String boosNian = "";
                        String[] s1 = splitBoss1.split(" ");
                        if (s1.length > 1) {
                            try {
                                int i1 = Integer.parseInt(s1[1]);
                                boosNian = s1[1];
                            } catch (Exception e) {
                                boosNian = s1[0];
                            }

                        } else {

                        }
                        ISSusBoss = boosNian + ";" + bossRest;
                        if (!MYISS.equals(ISSusBoss)) {
                            if (!MYISS.contains("UNKNOWN") && !myMedlineYear.contains("-")) {
                                handleCompareSize(resMapConpare, "iss错误+++");
                                //SmallTool.printMessError("iss错误+++" + pmid);
                                continue;

                            }
                        }

                    }

                    //摘要
                    String abText = pmDeatil.getAbText();
                    String abtextMy = "";
                    if (abText != null) {
                        Document parse = Jsoup.parse(abText);
                        abtextMy = parse.text();
                    }
                    String abs = entityBoss.getStr("abs");
                    Set<Map<String, String>> bossAbs = JSONObject.parseObject(abs, Set.class);
                    A:
                    for (Map<String, String> bossAb : bossAbs) {
                        Collection<String> values = bossAb.values();
                        for (String value : values) {
                            if (StringUtil.isNotNull(value)) {
                                if (!abtextMy.equals(value)) {
                                    handleCompareSize(resMapConpare, "摘要不一样+++");
                                    //SmallTool.printMessError("摘要不一样+++" + pmid);
                                    break A;
                                }
                            }
                        }
                    }
                    // 作者
                    String authorExtend = pmDeatil.getAuthorExtend();
                    Set<String> myAuSet = new HashSet<>();
                    if (authorExtend != null) {
                        List<PmDeatil.AuthorExtend> myaus = JSONArray.parseArray(authorExtend, PmDeatil.AuthorExtend.class);
                        myAuSet = myaus.stream().map(o -> {
                            String s = o.getForeName() + " " + o.getLastName() + " " + o.getSuffix();
                            if (StringUtil.isNull(s.trim())) {
                                s = o.getCollectiveName();
                            }
                            return s.trim();
                        }).collect(Collectors.toSet());
                    }
                    String bossName = entityBoss.getStr("authorSet");
                    List<String> bossNames = JSONArray.parseArray(bossName, String.class);
                    if (myAuSet.size() != bossNames.size()) {
                        handleCompareSize(resMapConpare, "作者属性数量不对+++");
                        //SmallTool.printMessError("作者属性不对+++" + pmid);
                        continue;
                    } else {
                        if (!bossNames.containsAll(myAuSet)) {
                            handleCompareSize(resMapConpare, "作者属性不对对不起来+++");
                            //SmallTool.printMessError("作者属性不对+++" + pmid);
                            continue;
                        }
                    }

                    // 作者对应的地址 需要核对两个位置 一个作者 一个是作者对应的单位
                    String meAuAndUnit = pmDeatil.getAuthorExtend();
                    List<PmDeatil.AuthorExtend> AuthorExtendMe = new ArrayList<>();
                    if (StringUtil.isNotNull(meAuAndUnit)) {
                        AuthorExtendMe = JSONObject.parseArray(meAuAndUnit, PmDeatil.AuthorExtend.class);
                    }
                    String authorMapBoss = entityBoss.getStr("authorMap");
                    String authorAddMapBoss = entityBoss.getStr("addressMap");
                    Map bossAuIdAdd = JSONObject.parseObject(authorMapBoss, Map.class);
                    // 转化数据 存储 作者 和作者对应的单位id 集合 集合用,
                    Map<String, String> authorUnitStrBoss = new HashMap<>();
                    Set<String> set = bossAuIdAdd.keySet();
                    for (String s : set) {
                        authorUnitStrBoss.put(s, bossAuIdAdd.get(s).toString());
                    }

                    Map<String, String> bossAuIdAddNum = JSONObject.parseObject(authorAddMapBoss, Map.class);
                    // 进行比对
                    T:
                    for (PmDeatil.AuthorExtend extend : AuthorExtendMe) {
                        String meAu = extend.getForeName() + " " + extend.getLastName() + " " + extend.getSuffix();
                        meAu = meAu.trim();
                        if (StringUtil.isNull(meAu)) {
                            meAu = extend.getCollectiveName();
                        }
                        List<String> allMeUnit = extend.getAffiliation();
                        if (authorUnitStrBoss.containsKey(meAu)) {
                            String s = authorUnitStrBoss.get(meAu);
                            List<String> strings = JSONArray.parseArray(s, String.class);
                            List<String> singleBoss = new ArrayList<>();
                            for (String string : strings) {
                                singleBoss.add(bossAuIdAddNum.get(string));
                            }
                            if (allMeUnit.size() != singleBoss.size()) {
                                handleCompareSize(resMapConpare, "作者对应的单位数量不一致+++");

                                //SmallTool.printMessError("作者对应的单位数量不一致+++" + pmid);
                                break T;
                            } else {
                                if (!allMeUnit.containsAll(singleBoss)) {
                                    handleCompareSize(resMapConpare, "作者对应的单位 不是很符合++++");
                                    //SmallTool.printMessError("作者对应的单位 不是很符合++++" + pmid);
                                    break T;
                                }
                            }
                        } else {
                            //SmallTool.printMessError("作者对应的单位不匹配");
                            handleCompareSize(resMapConpare, "作者对应的单位不匹配");
                            break T;
                        }

                    }
                } else {
                    //SmallTool.printMessError("老板不存在pmid+++" + pmid);
                    handleCompareSize(resMapConpare, "老板不存在pmid+++");
                    continue;
                }
//                SmallTool.printMess("结束比对pmid+++++++++++++++++++" + pmid);
            }
        }
        SmallTool.printMess("对比总数++" + effectSize);
        SmallTool.printMess(resMapConpare);
        SmallTool.printMess("+++doi一方有++" + JSON.toJSONString(pmidDoi));
        SmallTool.printMess("++++doi不同+++" + JSON.toJSONString(pmidDoiNoSame));

    }

    // 处理标题
    public static String handleStr(String str) {
        // 只留下字母数字和汉字
        //不好处理 情况太多了

//        if (str != null) {
//            if (str.startsWith("[") && str.endsWith("]")) {
//                str = str.substring(1, str.length() - 1);
//            }
//            if (str.endsWith(".")) {
//                str = str.substring(0, str.length() - 1);
//            } else {
//                str = str;
//            }
//        }
        return DelOther(str);
    }

    // 处理卷期页 与老板一致进行比对
    public static String handleIssue(String str) {
        if (StringUtil.isNull(str)) {
            return str;
        } else {
            String[] s = str.split(" ");
            StringBuffer stringBuffer = new StringBuffer();
            for (int i = 0; i < s.length; i++) {
                if (i == 2) {
                    boolean b = s[i].startsWith("0");
                    if (b) {
                        String replace = s[i].replace("0", "");
                        stringBuffer.append(replace);
                    } else {
                        stringBuffer.append(s[i]);
                    }

                } else {
                    stringBuffer.append(s[i] + " ");
                }
            }
            return stringBuffer.toString();

        }


    }

    public static String DelOther(String str) {
        return str.replaceAll("[^a-zA-Z0-9\\u4E00-\\u9FA5]", "").toUpperCase();
    }

    // 2022年3月16日13:47:20 转换成网页显示的mesh词格去掉*
    public static List<String> parseMesh(List<String> meshBoss) {
        List<String> res = new LinkedList<>();
        for (String boss : meshBoss) {
            res.add(boss.replace("*", ""));
        }
        return res;

    }


    public static Set<String> getErrorPts() {
        Set<String> pst = new HashSet<>();
        pst.add("Journal Article");
        return pst;
    }

    public static void handleCompareSize(Map<String, Integer> res, String param) {
        res.compute(param, (k, v) -> {
            if (v == null) {
                v = 1;
            } else {
                v = v + 1;
            }
            return v;

        });
    }


    // 存放pmid 对应的doi
    public static void handleCompareSizePmidDoi(Map<Integer, String> res, Integer pmid, String doi) {
        res.put(pmid, doi);

    }

}
